package com.hh.game.service.gateway.pool;

import com.hh.game.common.base.cache.redis.RedisResource;
import org.redisson.api.RMap;

import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Collectors;

public class WorkResultDataPoolRedis implements WorkResultDataPool {
    private RedisResource redisResource;
    private final static String BASE_KEY = "work-result-";
    private Map<Integer , Queue<Long>> cacheCount = new ConcurrentHashMap<>();
    private int oneUsercacheSize;

    public WorkResultDataPoolRedis(RedisResource redisResource ,int oneUsercacheSize) {
        this.redisResource = redisResource;
        this.oneUsercacheSize = oneUsercacheSize;
    }

    @Override
    public Object get(int userId, long requestId) {
        RMap<Long ,Object> cache = redisResource.getMap(BASE_KEY + userId);
        return cache.get(requestId);
    }

    @Override
    public void set(int userId, long requestId, Object result) {
        RMap<Long ,Object> cache = redisResource.getMap(BASE_KEY + userId);
        cache.put(requestId ,result);
        Queue<Long> record = new ConcurrentLinkedQueue<>();
        record = cacheCount.putIfAbsent(userId ,record);
        record.add(requestId);
        if(record.size() > oneUsercacheSize){
            Long[] removes = new Long[5];
            for(int i=0 ; i < 5 && record.size() > oneUsercacheSize ; i++){
                removes[i] = record.poll();
            }
            cache.fastRemoveAsync(removes);
        }
    }

    @Override
    public int size() {
        return (int)cacheCount.values().stream()
                .collect(Collectors.summarizingInt(queue -> queue.size())).getSum();
    }

    @Override
    public void clear() {
        cacheCount.keySet().stream().forEach(uid -> {
            RMap<Long ,Object> cache = redisResource.getMap(BASE_KEY + uid);
            cache.clear();
        });
    }
}
